#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <list>

#include "Adafruit_Keypad.h"
const char* id = "Lifi"; //定义两个字符串指针常量
const char* psw = "lS252525";

int LED_B = 27;
const char* host = "http://192.168.199.10:9999";
String token;
bool hasPlayer = false;
bool pause1 = false;
float rate = 1.0;
int ledPin = 4;

// 按下的按键
char key;
// 定义行引脚
byte rowPins[4] = {13, 12, 14, 27};
// 定义列引脚
byte colPins[4] = {26, 25, 33, 32};
// 定义键盘按键布局
char keys[4][4] = {
    {'1', '2', '3', 'A'},
    {'4', '5', '6', 'B'},
    {'7', '8', '9', 'C'},
    {'*', '0', '#', 'D'}
};

//iic驱动方式
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 18, /* data=*/ 23, /* reset=*/ U8X8_PIN_NONE);
Adafruit_Keypad customKeypad = Adafruit_Keypad(makeKeymap(keys), rowPins, colPins, 4, 4);

void httpPost(JsonDocument& doc, const String& url, String json){
    //空循环
    HTTPClient http; // 声明HTTPClient对象
    String u = host + url + "?api_token=" + token;
    http.begin(u); // 准备启用连接
    http.addHeader("Content-Type", "application/json");
    int httpCode = http.POST(json);
    if (httpCode > 0 && httpCode == HTTP_CODE_OK){
        // 如果状态码大于0说明请求过程无异常
        String body = http.getString(); // 读取服务器返回的响应正文数据
        // 如果正文数据很多该方法会占用很大的内存
        deserializeJson(doc, body);
    } else{
        Serial.println();
        Serial.printf("prerr: %s\n", u, http.errorToString(httpCode).c_str());
    }

    http.end(); // 结束当前连接
}

bool JustGet(const String url){
    HTTPClient http; // 声明HTTPClient对象
    String u = host + url + "?api_token=" + token;
    http.begin(u); // 准备启用连接
    int httpCode = http.GET(); // 发起GET请求
    return httpCode == HTTP_CODE_OK;
}

bool JustPost(const String url, String json){
    HTTPClient http; // 声明HTTPClient对象
    String u = host + url + "?api_token=" + token;
    http.begin(u); // 准备启用连接
    http.addHeader("Content-Type", "application/json");
    int httpCode = http.POST(json);
    return httpCode == HTTP_CODE_OK;
}

void httpGet(JsonDocument& doc, const String& url){
    //空循环
    HTTPClient http; // 声明HTTPClient对象

    String u = host + url + "?api_token=" + token;
    http.begin(u); // 准备启用连接
    int httpCode = http.GET(); // 发起GET请求
    if (httpCode > 0 && httpCode == HTTP_CODE_OK){
        // 如果状态码大于0说明请求过程无异常
        String body = http.getString(); // 读取服务器返回的响应正文数据
        // 如果正文数据很多该方法会占用很大的内存
        // Serial.println(body);
        deserializeJson(doc, body);
    } else{
        Serial.println();
        Serial.printf("grerr: %s\n", u, http.errorToString(httpCode).c_str());
    }

    http.end(); // 结束当前连接
}

// 播放状态
void setStatus(){
    JsonDocument doc;
    httpGet(doc, "/v1/mediaplayer/play/state");
    int index = doc["data"]["index"].as<int>(); //播放索引
    int is_paused = doc["data"]["is_paused"].as<int>(); //暂停或播放
    int is_playing = doc["data"]["is_playing"].as<int>(); //播放中
    pause1 = is_paused == 1;
    // Serial.println(index);

    hasPlayer = index != -1 || is_playing == 1;
    if (!hasPlayer){
        u8g2.firstPage();
        do{
            u8g2.setCursor(0, 12);
            u8g2.print("暂无播放！");
        } while (u8g2.nextPage());
    }
}

void getToken(){
    JsonDocument doc;
    httpPost(doc, "/v1/user/offline/login", "{\"offline_username\":\"super\",\"offline_password\":\"28c8edde3d61a0411511d3b1866f0636\"}");
    int code = doc["code"].as<int>();

    if (code == 200){
        token = doc["data"]["api_token"].as<String>();
        u8g2.firstPage();
        do{
            u8g2.setCursor(0, 12);
            u8g2.print("token 获取成功！");
        } while (u8g2.nextPage());
    }
}

void setup(){
    u8g2.begin();
    u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function

    pinMode(LED_B,OUTPUT);
    pinMode(ledPin,OUTPUT);
    digitalWrite(LED_B, LOW);
    digitalWrite(ledPin, LOW);
    //
    customKeypad.begin();

    Serial.begin(9600);
    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setFontDirection(0);

    WiFi.begin(id, psw);
    u8g2.firstPage();
    do{
        u8g2.setCursor(0, 12);
        u8g2.print("链接wifi");
        u8g2.setCursor(0, 45);
        u8g2.print("连接中...");
    } while (u8g2.nextPage());

    int num = 0;
    uint8_t m = 00;
    while (WiFi.status() != WL_CONNECTED){
        //未连接上
        delay(500);
        char m_str[10];
        strcpy(m_str, u8x8_u8toa(m, num));
        u8g2.print(m_str);
        Serial.println("zhengzailianjie...");
    }
    Serial.println("WiFi connected!");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    digitalWrite(LED_B, HIGH);
    // 登录
    getToken();
    Serial.println("login ok!" + token);
    // 播放中的检测
    setStatus();
    Serial.println("status get!");
}

void show(){
    JsonDocument doc;
    httpPost(doc, "/v1/mediaplayer/combine/get", "{\"list\":[]}");

    String name = doc["data"]["property"]["name"].as<String>();
    int duration = doc["data"]["duration"].as<int>();
    int elapsed = doc["data"]["elapsed"].as<int>();
    int is_paused = doc["data"]["is_paused"].as<int>();
    rate = doc["data"]["rate"].as<float>();
    String ratio = doc["data"]["ratio"].as<String>();
    String audio = doc["data"]["audio"]["title"].as<String>();
    String subtitle = doc["data"]["subtitle"]["title"].as<String>();
    float volume = doc["data"]["volume"].as<float>();

    pause1 = is_paused == 1;
    hasPlayer = duration - elapsed == 0;

    int ehour = elapsed / 60 / 60;
    int emin = elapsed / 60;
    int esend = elapsed % 60;
    int dhour = duration / 60 / 60;
    int dmin = duration / 60;
    int dsend = duration % 60;
    String time;
    time.concat(ehour);
    time.concat(':');
    time.concat(emin);
    time.concat(':');
    time.concat(esend);
    time.concat('/');
    time.concat(dhour);
    time.concat(':');
    time.concat(dmin);
    time.concat(':');
    time.concat(dsend);

    String r2;
    r2.concat("rate[");
    r2.concat(rate);
    r2.concat("],ratio[");
    r2.concat(ratio);
    r2.concat("]");

    int process = static_cast<float>(elapsed) / static_cast<float>(duration) * 125.f;
    int volume1 = 46 - volume / 2.f * 46.f + 17;

    u8g2.firstPage();
    do{
        // 顶部时间
        u8g2.setFont(u8g2_font_wqy14_t_gb2312);

        u8g2.drawStr(0, 12, pause1 ? ">" : "=");
        u8g2.drawStr(28, 12, time.c_str());
        u8g2.drawHLine(process, 13, 3);
        u8g2.drawHLine(0, 14, 128);
        u8g2.drawHLine(process, 15, 3);

        u8g2.setFont(u8g2_font_wqy12_t_gb2312);
        // 速度，尺寸
        u8g2.drawStr(0, 25, r2.c_str());
        // 字幕,音轨
        u8g2.setCursor(0, 37);
        u8g2.print("sub:" + subtitle);
        // 字幕,音轨
        u8g2.setCursor(0, 49);
        u8g2.print("aud:" + audio);
        // 名字
        // u8g2.setFont(u8g2_font_wqy12_t_gb2312);
        u8g2.setCursor(0, 62);
        u8g2.print(name);

        // 音量
        u8g2.drawVLine(126, 16, 1);
        u8g2.drawVLine(126, 63, 1);
        u8g2.drawVLine(125, 16, 48);
        u8g2.drawVLine(126, volume1, 48);
        u8g2.drawVLine(127, 16, 48);
    } while (u8g2.nextPage());
}

int time_scales = 0;

bool led1 = false;

// 1为播放,2为列表,3为音轨列表，4为字幕列表
char typePage = '2';
int pindex = 0;
JsonArray plist;
// std::list<JsonDocument> plist=;

void info(){
    // 保存读取到的按键值
    customKeypad.tick();
    if (customKeypad.available()){
        keypadEvent e = customKeypad.read();
        if (e.bit.EVENT == KEY_JUST_PRESSED){
            String tkey{(char(e.bit.KEY))};
            // 亮灯
            digitalWrite(ledPin, HIGH);
            led1 = true;
            Serial.println("A>>" + tkey);
            if (tkey == "A"){
                typePage = '2';
            } else if (tkey == "2"){
                String text = !pause1 ? "pause" : "resume";
                // 播放、暂停
                Serial.println("A>>" + text);
                JustGet("/v1/mediaplayer/pause/" + text);
            } else if (tkey == "7" || tkey == "9"){
                // 快进 快退
                String json = "{\"offset\": \"";
                json.concat(tkey == "7" ? "-" : "+");
                json.concat("10\"}");
                JustPost("/v1/mediaplayer/seek", json);
            } else if (tkey == "5" || tkey == "8"){
                // 音量
                String json = "{\"vol\": \"";
                json.concat(tkey == "8" ? "-" : "+");
                json.concat("0.1\"}");
                JustPost("/v1/mediaplayer/volume/set", json);
            } else if (tkey == "1" || tkey == "3"){
                // 上一个，下一个
                String text = tkey == "1" ? "prev" : "next";
                Serial.println("B>>" + text);
                JustGet("/v1/mediaplayer/playlist/" + text);
            } else if (tkey == "*" || tkey == "0"){
                // 倍速
                if (tkey == "*"){
                    rate += 0.15;
                } else{
                    rate = 1.0;
                }
                String json = "{\"rate\": \"";
                json.concat(rate);
                json.concat("\"}");
                JustPost("/v1/mediaplayer/play/rate/set", json);
            }
        }
    }
    // 大约8秒
    if (time_scales % 8 == 0){
        if (hasPlayer){
            show();
        } else{
            setStatus();
        }
    }
}

void clist(){
    Serial.println("110");
    JsonDocument doc;
    Serial.println("11");
    // if (sizeof(plist)/sizeof(plist[0]) == 0){
    if (pindex == 0){
        httpGet(doc, "/v1/movies/cinema/list");
        Serial.println("1");
        pindex = 1;
        plist = doc["data"]["list"].as<JsonArray>();
    }
    // String name = doc["data"]["list"][0]["name"].as<String>();
    // JsonArray list = doc["data"]["list"].as<JsonArray>();
    Serial.println("1.1");
    customKeypad.tick();
    if (customKeypad.available()){
        keypadEvent e = customKeypad.read();
        if (e.bit.EVENT == KEY_JUST_PRESSED){
            String tkey{(char(e.bit.KEY))};
            // 亮灯
            digitalWrite(ledPin, HIGH);
            led1 = true;
            Serial.println("A>>" + tkey);

            if (tkey == "B"){
                typePage = '1';
            } else if (tkey == "2" || tkey == "8"){
            } else if (tkey == "#"){
                // 确定
                typePage = '1';
            }
        }
    }
    // int soffect = 25;
    Serial.println("1.2");
    String nnn1 = plist[0]["name"].as<String>();
    String nnn2 = plist[1]["name"].as<String>();
    String nnn3 = plist[2]["name"].as<String>();
    String nnn4 = plist[3]["name"].as<String>();

    Serial.println("1.3");
    u8g2.firstPage();
    do{
        // 顶部时间
        u8g2.setFont(u8g2_font_wqy14_t_gb2312);
        u8g2.setCursor(0, 12);
        u8g2.print("播放列表");

        u8g2.setFont(u8g2_font_wqy12_t_gb2312);
        // 速度，尺寸
        u8g2.setCursor(0, 27);
        u8g2.print(nnn1);
        // // 字幕,音轨
        u8g2.setCursor(0, 37);
        u8g2.print(nnn2);
        // // 字幕,音轨
        u8g2.setCursor(0, 49);
        u8g2.print(nnn3);
        // // 名字
        u8g2.setCursor(0, 62);
        u8g2.print(nnn4);
    } while (u8g2.nextPage());
    Serial.println("2");
}

void loop(){
    Serial.println("5");
    if (token.isEmpty()){
        // 需要重启
    } else{
        String sssa = "6>";
        sssa.concat(typePage);
        Serial.println(sssa.c_str());
        switch (typePage){
        case '1': info();
            break;
        case '2': clist();
            break;
        // case '3': info();break;
        // case '4': info();break;
        }
    }
    // 大约3秒 用于监控按键的led
    if (time_scales % 3 == 0){
        digitalWrite(ledPin, LOW);
        led1 = true;
    }
    Serial.println("4");
    ++time_scales;
    delay(100);
    Serial.println("3");
}
